home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
flist.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
9KB
|
431 lines
/*
* $Id: flist.c,v 0.91 1994/02/20 00:52:55 zhao Pre-Release $
*
*. This file is part of BIT shareware package. After the two weeks of
* free evaluation period, you are encouraged (required) to register
* your copy for a small registration fee, which is $35 for personal use
* and $50 for commercial, government and institutional use.
*
* Copyright(c) 1993, 1994 by T.C. Zhao.
* All rights reserved.
*
* Permission to use, copy, and distribute this software in its entirety
* for non-commercial purposes is hereby granted, provided that the
* above shareware and copyright notices and this permission notice
* appear in all copies and their documentation.
*
* This software may be modified for your own use, but modified versions
* may not be distributed without prior consent of the author.
*
* This software is provided "as is" without expressed or implied
* warranty of any kind.
*
*.
*
* Active file list stuff. Standard keyed doubly linked list. The only
* missing function is append_dlist, which bit does not need.
* It would be nice if hashed ...
*
* All static function needs not to check parameters
*/
#if !defined(lint) && defined(F_ID)
char *id_flist = "$Id: flist.c,v 0.91 1994/02/20 00:52:55 zhao Pre-Release $";
#endif
#include "bit.h"
#include "dmalloc.h"
/* file list */
typedef struct flist_
{
struct flist_ *prev;
struct flist_ *next;
char fname[MAXFLEN];
}
FL;
/* directory list */
typedef struct
{
struct flist_ *head, *tail;
char dname[MAXDLEN];
}
DL;
static FL *
create_node(size_t nbytes)
{
FL *p;
if ((p = malloc(nbytes)))
{
p->prev = p->next = 0;
p->fname[0] = '\0';
}
return p;
}
static void
free_node(FL * node)
{
node->fname[0] = '\0';
free(node);
}
/*****************************************************************
* given a filename and flist head, find and return the node that
* contains filename
*****************************************************************/
static FL *
dl_search(FL * head, const char *str)
{
register FL *p;
for (p = head; p && strcmp(p->fname, str); p = p->next)
;
return p;
}
/****** free a doubley-linked flist *****/
static void
dl_free(FL * head)
{
FL *p, *q;
for (p = head; p; p = q)
{
q = p->next;
free_node(p);
}
}
#define MAXDIR 10 /* max directories */
static DL dlist[MAXDIR];
#ifdef FLIST_DBG
static int flist_msg_level = 0;
#else
static int flist_msg_level = 1;
#endif
/**************************************************************
* error messages, subject to msg_level filtering:
* 0 is considered by the message generating routine to be
* a warning, while 1 is considered to be a nice-to-have
* information and by default will not be printed.
**************************************************************/
static void
flist_msg(const char *func, const char *dir, const char *f)
{
M_msg(flist_msg_level, __FILE__, -1)
(func, "dir=%s\t\tf=%s", dir ? dir : "null", f ? f : "null");
}
/*******************************************************************
* Insert file f from directory dir to the active file list
*******************************************************************/
int
add_to_list(const char *dir, const char *f)
{
int slot;
static int warned;
FL *p;
DL *q = dlist, *qs;
if (!dir || !f || !*f)
return -1;
flist_msg("add", dir, f);
/* search for master head */
for (slot = 0, qs = q + MAXDIR; !slot && q < qs; q++)
slot = (!q->head || !q->dname[0] || !strcmp(q->dname, dir));
if (!slot)
{ /* no available space for this dir */
if (!warned)
{
Bark("AddToFlist", "No directory slot left");
warned = 1; /* bitching more than once is distasteful */
}
return -1;
}
/* ok. Insert file */
--q; /* for loop overshoots one */
/* create note first */
p = create_node(sizeof(FL));
strncpy(p->fname, f, MAXFLEN);
if (q->head)
{
q->head->prev = p;
p->next = q->head;
}
else
{
strncpy(q->dname, dir, MAXDLEN);
}
q->head = p;
if (!q->tail)
q->tail = q->head;
return 0;
}
static DL *
get_dl(const char *dir)
{
DL *q = dlist, *qs;
for (qs = q + MAXDIR; q < qs && strcmp(q->dname, dir); q++)
;
return q == qs ? 0 : q;
}
static FL *current; /* current position on FL */
int
delete_from_list(const char *dir, const char *f)
{
FL *p, *e;
DL *q;
flist_msg("Delete", dir, f);
if (!dir || !f)
return -1;
if (!(q = get_dl(dir)))
return -1;
for (p = q->head; p && strcmp(p->fname, f) != 0; p = p->next)
;
if (!p)
return -1; /* not found */
e = p;
if (q->head == p)
{
if ((q->head = q->head->next))
q->head->prev = 0;
else /* empty list */
q->tail = 0;
}
else if (q->tail == p)
{
if ((q->tail = q->tail->prev))
q->tail->next = 0;
else
q->head = 0;
}
else
{ /* remove it */
p->prev->next = p->next;
p->next->prev = p->prev;
}
if (!q->head)
{ /* this dir is gone */
q->dname[0] = '\0'; /* and signal so */
}
/* if the node happens to be the current node, need to backup one */
if (current == e)
current = current->prev;
free_node(e);
return 0;
}
int
is_on_list(const char *dir, const char *f)
{
DL *q = (dir && f) ? get_dl(dir) : 0;
return q ? (dl_search(q->head, f) != 0) : 0;
}
static int pindex;
/**********************************************************************
* Check if current active file list is empty
**********************************************************************/
int
is_empty_list(void)
{
int k = 0;
DL *q = dlist + pindex;
FL *more = current;
int imore = pindex;
if (!q->dname[0])
more = 0;
if (more && (more = more->next))
return 0;
while (!more && k < MAXDIR)
{
++imore;
imore %= MAXDIR;
if ((q = dlist + imore)->head && q->dname[0])
more = q->head;
k++;
}
return more == 0;
}
const char *
next_file(void)
{
int k = 0;
DL *q = dlist + pindex;
if (!q->dname[0])
current = 0;
if (current && (current = current->next))
return current->fname;
while (!current && k < MAXDIR)
{
++pindex;
pindex %= MAXDIR;
if ((q = dlist + pindex)->head && q->dname[0])
current = q->head;
k++;
}
if (!current)
{
Bark("NextFile", "Empty list");
return 0;
}
else
{
chdir(q->dname);
flist_msg("Next", q->dname, current->fname);
}
return current->fname;
}
const char *
prev_file(void)
{
int k = 0;
DL *q = dlist + pindex;
if (!q->dname[0])
current = 0;
if (current && (current = current->prev))
return current->fname;
while (!current && k < MAXDIR)
{
++pindex;
pindex %= MAXDIR;
if ((q = dlist + pindex)->tail && q->dname[0])
current = q->tail;
k++;
}
if (!current)
{
Bark("PrevFile", "Empty list");
return 0;
}
else
{
chdir(q->dname);
flist_msg("Prev", q->dname, current->fname);
}
return current->fname;
}
/****************************************************************
* given a filename, try to locate the directory it is in
****************************************************************/
static char *
which_dir(const char *f)
{
DL *q = dlist, *qs;
for (qs = q + MAXDIR; q < qs && dl_search(q->head, f) == 0; q++)
;
return q ? q->dname : 0;
}
/****************************************************************
* given a filename only, try to delete the file from the list
****************************************************************/
int
delete_from_list1(const char *f)
{
char cdir[MAXDLEN + 2];
if (!f)
return -1;
/* try current directory first */
getcwd(cdir, MAXDLEN);
/* search list for directory */
return (delete_from_list(cdir, f) >= 0) ||
delete_from_list(which_dir(f), f) >= 0;
}
int
make_list(int n, char *list[])
{
static char dirn[MAXDLEN], fn[MAXFLEN];
int i;
if (n < 1)
return -1;
if (n > 15)
show_busy("MakingList ...");
for (i = n; --i >= 0;)
{
if (split_fname(dirn, fn, list[i]) == 0)
{
if (dirn[strlen(dirn) - 1] != '/')
strcat(dirn, "/");
if (fn[0])
add_to_list(dirn, fn);
}
}
end_busy();
return 0;
}
/* empty all lists */
void
cleanup_files(void)
{
DL *q = dlist, *qs;
for (qs = q + MAXDIR; q < qs; q++)
if (q->dname[0])
{
dl_free(q->head);
q->dname[0] = '\0';
q->head = q->tail = 0;
}
}